// Package cloud 实现了云服务管理组件
//
// 架构设计：
// 1. CloudService: 顶层服务管理器
//    - 协调各个子组件
//    - 管理组件生命周期
//    - 提供统一的对外接口
//
// 2. 子组件：
//    - Publisher: 消息发布器
//    - CommandManager: 命令管理
//    - ConnectionManager: 连接管理
//    - ConfigManager: 配置管理
//
// 本文件实现了云服务管理器，它负责：
// - 管理与云端的通信（HTTP和MQTT）
// - 处理数据上传和命令下发
// - 维护心跳检测
// - 管理配置同步
//
// 主要功能：
// 1. 数据管理
//    - 数据上传队列
//    - 数据缓存
//    - 失败重试
//
// 2. 通信管理
//    - HTTP客户端：用于RESTful API通信
//    - MQTT客户端：用于实时消息通信
//    - 心跳检测：保持连接活跃
//
// 3. 命令处理
//    - 接收云端命令
//    - 命令验证和执行
//    - 响应结果上报
//
// 4. 配置管理
//    - 从配置服务获取配置
//    - 动态更新MQTT连接参数
//    - 配置变更处理
//
// 使用方式：
//  service, err := cloud.NewService(configInf)
//  if err != nil {
//      // 处理错误
//  }
//
//  // 启动服务
//  if err := service.Start(ctx); err != nil {
//      // 处理错误
//  }
//
//  // 发送数据
//  service.SendData(data)
//
//  // 停止服务
//  service.Stop()

package cloud

import (
	"context"
	"fmt"
	"net/http"
	"sync"
	"time"

	"gitee.com/rw555/fdsmastergo/pkg/config"
	"gitee.com/rw555/fdsmastergo/pkg/logger"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// CloudService 云服务管理器
type CloudService struct {
	systemConfig map[string]interface{}
	connMgr      *ConnectionManager
	publisher    *Publisher
	subscriber   *Subscriber
	wg           sync.WaitGroup
	stopChan     chan struct{}
	httpServer   *http.Server
}

// NewCloudService 创建云服务
func NewCloudService() (*CloudService, error) {
	service := &CloudService{
		stopChan: make(chan struct{}),
	}

	// 加载配置
	configClient := config.NewClient("http://localhost:8082")
	systemConfig, err := configClient.LoadConfigs()
	if err != nil {
		return nil, fmt.Errorf("加载配置失败: %w", err)
	}
	service.systemConfig = systemConfig
	configClient.PrintConfigs(systemConfig)

	// 创建连接管理器
	connMgr, err := NewConnectionManager(service.systemConfig)
	if err != nil {
		return nil, fmt.Errorf("创建连接管理器失败: %w", err)
	}
	service.connMgr = connMgr

	// 创建消息订阅器
	service.subscriber = NewSubscriber(connMgr, configClient)

	// 创建消息发布器
	service.publisher = NewPublisher(connMgr, configClient)
	service.subscriber.SetPublisher(service.publisher)

	return service, nil
}

// Start 启动云服务
func (s *CloudService) Start(ctx context.Context) error {
	// 启动HTTP服务器
	if err := s.startHTTPServer(); err != nil {
		return fmt.Errorf("启动HTTP服务器失败: %w", err)
	}

	// 启动连接管理器
	if err := s.connMgr.Start(ctx); err != nil {
		return fmt.Errorf("启动连接管理器失败: %w", err)
	}

	// 启动消息订阅器
	if err := s.subscriber.Start(ctx); err != nil {
		return fmt.Errorf("启动消息订阅器失败: %w", err)
	}

	// 启动消息发布器
	if err := s.publisher.Start(ctx); err != nil {
		return fmt.Errorf("启动消息发布器失败: %w", err)
	}

	logger.SystemInfo("云服务启动成功")
	return nil
}

// Stop 停止云服务
func (s *CloudService) Stop() {
	// 停止HTTP服务器
	if s.httpServer != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		if err := s.httpServer.Shutdown(ctx); err != nil {
			logger.SystemError("关闭HTTP服务器失败", zap.Error(err))
		}
	}

	// 停止消息订阅器
	s.subscriber.Stop()

	// 停止消息发布器
	s.publisher.Stop()

	// 停止连接管理器
	s.connMgr.Stop()

	logger.SystemInfo("云服务已停止")
}

// startHTTPServer 启动HTTP服务器
func (s *CloudService) startHTTPServer() error {
	gin.SetMode(gin.ReleaseMode)
	router := gin.New()
	router.Use(gin.Recovery())

	// API路由
	v1 := router.Group("/api/v1")
	{
		v1.POST("/refresh-config", s.handleRefreshConfig)
	}

	s.httpServer = &http.Server{
		Addr:    ":8084",
		Handler: router,
	}

	// 在后台启动HTTP服务
	go func() {
		if err := s.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			logger.SystemError("HTTP服务异常退出", zap.Error(err))
		}
	}()

	logger.SystemInfo("HTTP服务已启动", zap.String("port", s.httpServer.Addr))
	return nil
}

// handleRefreshConfig 处理配置刷新请求
func (s *CloudService) handleRefreshConfig(c *gin.Context) {
	logger.SystemInfo("收到配置刷新请求")

	// 重新加载配置
	configClient := config.NewClient("http://localhost:8082")
	newConfig, err := configClient.LoadConfigs()
	if err != nil {
		logger.SystemError("加载配置失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "加载配置失败"})
		return
	}

	// 更新系统配置
	s.systemConfig = newConfig

	// 重新配置连接管理器
	if err := s.connMgr.UpdateConfig(newConfig); err != nil {
		logger.SystemError("更新连接管理器配置失败", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新连接管理器配置失败"})
		return
	}

	logger.SystemInfo("MQTT配置已刷新")
	c.JSON(http.StatusOK, gin.H{"message": "配置已刷新"})
}
